﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AliyunOss;
using AutoMapper;
using Kalman;
using Kalman.Jwt;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using NLog;
using RestSharp;
using Wechat.MiniApp;
using Wechat.TenpayV3;
using WxPayAPI;
using static QRCoder.PayloadGenerator;

namespace QuDao.Api.Controllers
{
    /// <summary>
    /// 微信小程序服务端相关API
    /// </summary>
    [AllowAnonymous]
    //[ApiExplorerSettings(IgnoreApi = true)]
    public class WxAppController : ApiControllerBase
    {
        readonly AliyunOssClient oss;
        readonly JwtBuilder jwt;
        readonly IMapper _mapper;
        public WxAppController(AliyunOssClient aliyunOssClient, JwtBuilder jwtBuilder, IMapper mapper)
        {
            oss = aliyunOssClient;
            jwt = jwtBuilder;
            _mapper = mapper;
        }

        /// <summary>
        /// 重新加载微信应用数据（刷新缓存）
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public int ReloadApp()
        {
            return WxAppBO.Instance.Reload();
        }

        ///// <summary>
        ///// 重新加载微信商户数据（刷新缓存）
        ///// </summary>
        ///// <returns></returns>
        //[HttpGet]
        //public int ReloadMerchant()
        //{
        //    return MerchantBO.Instance.Reload();
        //}

        /// <summary>
        /// 获取微信小程序服务端API访问令牌
        /// </summary>
        /// <param name="appid">微信小程序应用ID</param>
        /// <returns></returns>
        [HttpGet]
        public string GetAccessToken([FromHeader] string appid)
        {
            return WxAppClient.Instance.GetAccessToken(appid);
        }

        /// <summary>
        /// 获取微信小程序会话数据（session_key和openid）
        /// </summary>
        /// <param name="appid">微信小程序AppID</param>
        /// <param name="code">前端通过调用wx.login方法获取到的登录凭证</param>
        /// <returns></returns>
        [HttpGet]
        public WxaSessionModel GetWxaSession([FromHeader] string appid, string code)
        {
            return WxAppClient.Instance.GetWxaSession(appid, code);
        }

        ///// <summary>
        ///// 微信用户授权登录，返回用户信息（包含多租户账号信息）及接口访问令牌
        ///// </summary>
        //[HttpPost]
        //public LoginUserModel Login([FromHeader] string appid, WxLoginDto dto)
        //{
        //    var user = UserBO.Instance.Login(appid, dto);

        //    var model = _mapper.Map<LoginUserModel>(user);

        //    //model.AccessToken = jwt.SetJwtID<long>(model.UserID).AddClaim("OpenID", model.OpenID).Encode();
        //    model.AccessToken = jwt.SetJwtID(model.UserID).Encode();
        //    model.RefreshToken = jwt.Encode(true);
        //    //model.AccountList = AccountBO.Instance.GetListByUser(user.UserID);

        //    UserBO.Instance.Update(user.UserID, "AccessToken", model.AccessToken);

        //    return model;
        //}

        /// <summary>
        /// 用户登录
        /// </summary>
        [HttpPost]
        [CacheByHeader(10, "tid", "mobile", "verifyCode")]
        [ExecutingLock(ExecutingLockMode.ActionSingle)]
        public LoginUserModel Login([FromHeader] int tid, string mobile, string verifyCode = "")
        {
            var user = UserBO.Instance.Login(tid, mobile, verifyCode);

            var model = _mapper.Map<LoginUserModel>(user);

            //model.AccessToken = jwt.SetJwtID<long>(model.UserID).AddClaim("OpenID", model.OpenID).Encode();
            model.AccessToken = jwt.SetJwtID(model.UserID).Encode();
            model.RefreshToken = jwt.Encode(true);
            //model.AccountList = AccountBO.Instance.GetListByUser(user.UserID);

            UserBO.Instance.Update(user.UserID, "AccessToken", model.AccessToken);

            return model;
        }

        /// <summary>
        /// 根据刷新令牌获取新的令牌数据（如果刷新令牌也过期的话，跳到登录界面重新获取令牌）
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        [HttpGet]
        public LoginUserModel GetTokenByRefresh(string refreshToken)
        {
            var dic = jwt.Decode(refreshToken, true);
            if (!dic.ContainsKey("refresh")) throw new AppException("无效的刷新令牌", "401");

            var userID = long.Parse(dic["jti"].ToString());
            var model = UserBO.Instance.GetItem<LoginUserModel>(userID);

            //model.AccessToken = jwt.SetJwtID<int>(userID).AddClaim("OpenID", model.OpenID).Encode();
            model.AccessToken = jwt.SetJwtID(userID).Encode();
            model.RefreshToken = jwt.Encode(isRefresh: true);

            return model;
        }

        /// <summary>
        /// 对微信小程序返回的用户敏感数据进行解密
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string DecryptData([FromBody] WxaDataModel model)
        {
            if (model == null) throw new AppException("数据不能为空");

            var result = WxAppClient.Instance.AESDecrypt(model.Data, model.SessionKey, model.IV);
            return result;
        }

        /// <summary>
        /// 获取微信小程序码（接口A，数量限制10万）
        /// </summary>
        /// <param name="appid">微信小程序应用ID</param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public string GetWxaCode([FromHeader] string appid, [FromBody] WxaCodeModel model)
        {
            var data = WxAppClient.Instance.GetWxaCode(appid, model);
            var ossKey = $"circle/qrcode-{DateTime.Now:yyyyMM}/{GuidUtil.New32Lower()}.png";
            oss.PutImage(ossKey, data);

            return oss.Options.BindDomainUrl + ossKey;
        }

        /// <summary>
        /// 获取微信小程序码（接口B，数量不受限）
        /// </summary>
        /// <param name="appid">微信小程序应用ID</param>
        /// <param name="model"></param>
        /// <returns>返回小程序码图片路径</returns>
        [HttpPost]
        public string GetUnlimitedWxaCode([FromHeader] string appid, [FromBody] WxaCodeUnlimitedModel model)
        {
            var data = WxAppClient.Instance.GetUnlimitedWxaCode(appid, model);
            var ossKey = $"circle/qrcode-{DateTime.Now:yyyyMM}/{GuidUtil.New32Lower()}.png";
            oss.PutImage(ossKey, data);

            return oss.Options.BindDomainUrl + ossKey;
        }

        //[HttpPost]
        //public string QueryUrlScheme([FromHeader] string appid, string scheme)
        //{
        //    var data = WxAppClient.Instance.QueryUrlScheme(appid, scheme);

        //    return data;
        //}

        [HttpPost]
        public string IDCardOCR(string appid, string imgUrl)
        {
            var result = WxAppClient.Instance.IDCardOCR(appid, imgUrl);
            return result;
        }

        ///// <summary>
        ///// 小程序发起支付请求前先向服务端获取支付请求参数字符串
        ///// </summary>
        ///// <param name="appid">微信小程序应用ID</param>
        ///// <param name="tradeOrderID">交易订单ID（注意：非业务订单ID）</param>
        ///// <param name="openID">用户OpenID</param>
        ///// <returns></returns>
        //[HttpPost]
        //[AllowAnonymous]
        //public IDictionary<string,string> GetWxaPayParameter([FromHeader] string appid, string openID, long tradeOrderID)
        //{
        //    var dic = PaymentBO.Instance.GeneratePayParameters(appid, openID, tradeOrderID);
        //    return dic;
        //}

        /// <summary>
        /// 微信支付 - 查询交易订单（transaction_id和out_trade_no二选一）
        /// </summary>
        /// <param name="appid">微信小程序应用ID</param>
        /// <param name="transaction_id">微信支付交易ID</param>
        /// <param name="out_trade_no">商户订单号（加前缀）</param>
        /// <param name="isNotify">是否处理补单通知，默认false，不处理</param>
        /// <returns></returns>
        [HttpGet]
        public TransactionData QueryOrder([FromHeader] string appid, string transaction_id, string out_trade_no, bool isNotify = false)
        {
            var app = WxAppBO.Instance.GetItem(appid);
            if (app == null) throw new AppException($"无效的应用：{appid}");

            return TenpayClient.Instance.QueryOrder(app, transaction_id, out_trade_no, isNotify);
        }

        /// <summary>
        /// 微信支付 - 关闭交易订单
        /// </summary>
        /// <param name="appid">微信小程序应用ID</param>
        /// <param name="out_trade_no">商户订单号（加前缀）</param>
        [HttpGet]
        public void CloseOrder([FromHeader] string appid, string out_trade_no)
        {
            var app = WxAppBO.Instance.GetItem(appid);
            if (app == null) throw new AppException($"无效的应用：{appid}");

            TenpayClient.Instance.CloseOrder(app, out_trade_no);
        }

        ///// <summary>
        ///// 微信支付 - 处理支付通知
        ///// </summary>
        //[HttpPost("{mchid}")]
        //public string PayNotify(string mchid)
        //{
        //    var sign = string.Empty;
        //    if (Request.Headers.ContainsKey("Wechatpay-Signature")) sign = Request.Headers["Wechatpay-Signature"].ToString();
        //    var body = Request.GetBodyString();
        //    if (string.IsNullOrEmpty(body)) return "request body cannot be empty";

        //    string success = "{ \"code\": \"SUCCESS\", \"message\": \"成功\" }";
        //    string fail = "{ \"code\": \"FAIL\", \"message\": \"失败\" }";

        //    var data = TenpayClient.Instance.ParsePayNotify(mchid, body, sign);
        //    var flag = PaymentBO.Instance.PayNotify(data);

        //    return flag ? success : fail;
        //}

        ///// <summary>
        ///// 微信支付 - 处理支付通知（补单操作）
        ///// </summary>
        ///// <param name="json"></param>
        ///// <returns></returns>
        //[HttpPost]
        //public bool PayNotify2([FromForm] string json)
        //{
        //    var data = new TransactionData(json);
        //    var flag = PaymentBO.Instance.PayNotify(data);
        //    return flag;
        //}

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="text">待加密的文本内容</param>
        /// <returns></returns>
        [HttpPost]
        public string Encrypt(string text)
        {
            return TenpayClient.Instance.Encrypt(text);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="text">待解密的文本内容</param>
        /// <returns></returns>
        [HttpPost]
        public string Decrypt(string text)
        {
            return TenpayClient.Instance.Decrypt(text);
        }


        //统一服务消息：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/uniform-message/uniformMessage.send.html

        //订阅消息：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html

        //物流助手：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.addOrder.html

        //图像处理（智能裁剪，条码/二维码识别，高清化）：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/img/img.aiCrop.html

    }
}
